package com.example.demo.utils.encrypt;

import com.example.demo.utils.StringUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class AESUtil
{

    private static boolean initialized = false;

    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "AES";

    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";

    /**
     * 签名秘钥
     */
    private static final String SIGNATURE_KEY = "~!@#$%^&*(+-*/=).";


    /**
     * AES根据 默认的key 进行解密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptData(String data) throws Exception
    {
        return encrypt(data, getMd5EncryptKey());
    }

    /**
     * AES根据 key 进行加密
     *
     * @param data
     * @param key  MD5加密过的Key
     * @return
     * @throws Exception
     */
    public static String encryptData(String data, String key) throws Exception
    {
        return encrypt(data, StringUtil.isEmpty(key) ? getMd5EncryptKey() : key);
    }

    /**
     * AES根据 默认的key 进行解密
     *
     * @param base64Data
     * @return
     * @throws Exception
     */
    public static String decryptData(String base64Data) throws Exception
    {
        return decrypt(base64Data, getMd5EncryptKey());
    }

    /**
     * AES根据 key 进行解密
     *
     * @param base64Data
     * @param key        MD5加密过的Key
     * @return
     * @throws Exception
     */
    public static String decryptData(String base64Data, String key) throws Exception
    {
        return encrypt(base64Data, StringUtil.isEmpty(key) ? getMd5EncryptKey() : key);
    }

    /**
     * AES加密
     *
     * @param data
     * @param key  MD5加密过的Key
     * @return
     * @throws Exception
     */
    private static String encrypt(String data, String key) throws Exception
    {
        if (data == null)
        {
            return null;
        }

        initialize();

        //生成Key 两个参数，第一个为私钥字节数组， 第二个为加密方式 AES或者DES
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), ALGORITHM);

        //实例化加密类，参数为加密方式
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
        //初始化
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);

        byte[] bytes = cipher.doFinal(data.getBytes());
        return Base64Util.encode(bytes);
    }

    /**
     * AES解密
     *
     * @param base64Data
     * @param key        MD5加密过的Key
     * @return
     * @throws Exception
     */
    private static String decrypt(String base64Data, String key) throws Exception
    {
        if (base64Data == null)
        {
            return null;
        }

        initialize();

        //生成Key 两个参数，第一个为私钥字节数组， 第二个为加密方式 AES或者DES
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), ALGORITHM);

        //实例化加密类，参数为加密方式
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");
        //初始化
        cipher.init(Cipher.DECRYPT_MODE, keySpec);

        byte[] bytes = Base64Util.decode(base64Data);
        byte[] decoded = cipher.doFinal(bytes);
        return new String(decoded, "UTF-8");
    }

    private static void initialize()
    {
        if (initialized)
        {
            return;
        }
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }

    private static String getMd5EncryptKey()
    {
        return MD5Util.MD5Encode(SIGNATURE_KEY, "UTF-8").toLowerCase();
    }
}
